﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace ico2cur
{
    public partial class Ico2Cur : Form
    {
        public Ico2Cur()
        {
            InitializeComponent();

            m_IconPreview = new IconPreview();
            m_IconPreview.Dock = DockStyle.Right;
            m_IconPreview.Anchor = AnchorStyles.Top;
            m_IconPreview.Location = new Point(m_HotspotGroupBox.Width - 165, 10);
            m_IconPreview.Size = new Size(160, 160);
            m_HotspotGroupBox.Controls.Add(m_IconPreview);
            m_IconPreview.Click += M_IconPreview_Click;

            m_AboutMenuItem = new MenuItem("About... ", new EventHandler(M_AboutMenuItem_Event), Shortcut.F1);
            ContextMenu menu = new ContextMenu();
            menu.MenuItems.Add(m_AboutMenuItem);
            ContextMenu = menu;
        }

        private void M_AboutMenuItem_Event(object sender, EventArgs e)
        {
            AboutDialog dlg = new AboutDialog();

            dlg.AppIcon = ico2cur.Properties.Resources.ico2cur;
            dlg.AppName = "TS Ico2Cur";
            dlg.AppVersion = "ver. 1.0";
            dlg.AppCopyright = "Copyright (c) 2017 by Tobiasz Stamborski";
            dlg.AppDescription = "Fine and easy converter from *.ico to *.cur files.";
            dlg.Licence = "The MIT License (MIT)\r\nCopyright (c) 2017 Tobiasz Stamborski\r\n\r\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the\r\nSoftware without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of the Software,\r\nand to permit persons to whom the Software is furnished to do so, subject to the following conditions:\r\n\r\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR\r\nANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH\r\nTHE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.";

            dlg.ShowDialog();
        }

        private void M_IconPreview_Click(object sender, EventArgs e)
        {
            m_XHotspot.Value = m_IconPreview.Hotspot.X;
            m_YHotspot.Value = m_IconPreview.Hotspot.Y;
        }

        private void m_OpenBtn_Click(object sender, EventArgs e)
        {
            OpenFileDialog dlg = new OpenFileDialog();

            dlg.DefaultExt = "*.ico";
            dlg.Filter = "Icon Files (*.ico)|*.ico";
            dlg.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
            dlg.CheckFileExists = true;
            dlg.CheckPathExists = true;
            dlg.Multiselect = false;
            dlg.Title = "Open *.ico file... ";

            if (dlg.ShowDialog() == DialogResult.OK)
            {
                m_FilePathBox.Text = dlg.FileName;
                m_HotspotGroupBox.Enabled = true;
                m_IconPreview.Icon = new Icon(dlg.FileName);
                m_XHotspot.Maximum = m_IconPreview.Icon.Width - 1;
                m_YHotspot.Maximum = m_IconPreview.Icon.Height - 1;
                m_ConvertBtn.Enabled = true;
            }
        }

        private IconPreview m_IconPreview;
        private MenuItem m_AboutMenuItem;

        private void m_XHotspot_ValueChanged(object sender, EventArgs e)
        {
            m_IconPreview.Hotspot = new Point((int)m_XHotspot.Value, m_IconPreview.Hotspot.Y);
        }

        private void m_YHotspot_ValueChanged(object sender, EventArgs e)
        {
            m_IconPreview.Hotspot = new Point(m_IconPreview.Hotspot.X, (int)m_YHotspot.Value);
        }

        private unsafe void m_ConvertBtn_Click(object sender, EventArgs e)
        {
            SaveFileDialog dlg;
            FileStream fstream;
            BinaryReader reader;
            BinaryWriter writer;
            byte[] data;
            UInt16 * head16_r, head16_t, head16_n;
            UInt32 * head32_bsize, head32_offset;
            byte * head8_r;


            //wczytaja plik ikony
            try
            {
                fstream = new FileStream(m_FilePathBox.Text, FileMode.Open, FileAccess.Read);
            }
            catch (IOException ioe)
            {
                MessageBox.Show(ioe.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            reader = new BinaryReader(fstream);
            data = new byte[fstream.Length];
            for (int i = 0; i < fstream.Length; i++)
                data[i] = (byte)fstream.ReadByte();
            fstream.Close();

            //spr naglowka struktury icondir
            fixed (byte* datap = &data[0])
            {
                head16_r = (UInt16*)(datap + 0);
                head16_t = (UInt16*)(datap + 2);
                head16_n = (UInt16*)(datap + 4);
                //czy poprawny plik ikony
                if (*head16_r != 0x0000 || *head16_t != 0x0001)
                {
                    MessageBox.Show("Invalid icon file.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }
                *head16_t = 0x0002; //to teraz bedzie kursor...
                                    //czy to jest pojedyncza ikona
                                    //byc moze potem wykomentowac
                                    //if (*head16_n != 0x0001)
                                    //{
                                    //MessageBox.Show("Sorry, this app doesn't support multiple packed icons.",
                                    //"Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                                    //return;
                                    //}

                //spr i przeprawienie struktury ICONDIRENTRY
                head8_r = (datap + 6 + 3);
                if (*head8_r != 0x00)
                {
                    MessageBox.Show("Invalid icon file.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }
                //zapisanie wspolrzednych hotspot'a
                head16_t = (UInt16*)(datap + 6 + 4); //poziomo - x
                head16_n = (UInt16*)(datap + 6 + 6); //pionowo - y
                *head16_t = (UInt16)m_XHotspot.Value;
                *head16_n = (UInt16)m_YHotspot.Value;
                //wczytanie wielkosci i offset'u bitmapy
                head32_bsize = (UInt32*)(datap + 6 + 8);
                head32_offset = (UInt32*)(datap + 6 + 12);

                dlg = new SaveFileDialog();
                dlg.DefaultExt = "*.cur";
                dlg.FileName = "cursor1.cur";
                dlg.Filter = "Cursor Files (*.cur)|*.cur";
                dlg.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
                dlg.CheckPathExists = true;
                dlg.Title = "Save As... ";

                if (dlg.ShowDialog() == DialogResult.OK)
                {
                    try
                    {
                        fstream = new FileStream(dlg.FileName, FileMode.Create, FileAccess.Write);
                    }
                    catch (IOException ioe)
                    {
                        MessageBox.Show(ioe.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        return;
                    }

                    writer = new BinaryWriter(fstream);
                    //naglowek
                    for (int i = 0; i < 6; i++)
                        writer.Write(*(datap +i));
                    //ICONDIRENTRY
                    for (int i = 6; i < (6 + 16); i++)
                        writer.Write(*(datap + i));
                    //obrazek
                    for (UInt32 i = 0; i < (*head32_bsize); i++)
                        writer.Write(*(datap + *head32_offset + i));

                    fstream.Close();
                }
            }
        }
    }
}
